package com.tarena.csmall.seckill.init;

import cn.tedu.mall.pojo.seckill.vo.SeckillSkuVO;
import cn.tedu.mall.pojo.seckill.vo.SeckillSpuVO;
import com.alibaba.fastjson.JSON;
import com.tarena.csmall.seckill.mapper.SeckillSkuMapper;
import com.tarena.csmall.seckill.mapper.SeckillSpuMapper;
import com.tarena.csmall.seckill.service.SeckillSkuService;
import com.tarena.csmall.seckill.service.SeckillSpuService;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Component;

@Component
@Slf4j
public class SeckillInitializer {
    public void init(){
        //将所有预热数据写入到redis中
        System.out.println("预热数据初始化完成");
        //初始化 表格中所有的spu 和sku数据包括3部分缓存数据
        initSpus();
    }
    @Autowired
    private SeckillSpuMapper seckillSpuMapper;
    @Autowired
    private SeckillSkuMapper seckillSkuMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    private void initSpus() {
        //读取数据库 seckill_spu select * from seckill_spu
        List<SeckillSpuVO> spus=seckillSpuMapper.selectAll();
        System.out.println(spus);
        //将数据按照redis要求存储
        String spusKey= SeckillSpuService.SECKILL_SPU_LIST;
        //准备好redis操作string对象
        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        //准备好redis操作list对象
        ListOperations<String, String> opsForList = stringRedisTemplate.opsForList();
        List<String> spuJsons=new ArrayList<>();
        for (SeckillSpuVO spuVO : spus) {
            Long spuId=spuVO.getId();
            //准备一下sku的预热数据
            List<SeckillSkuVO> skus=seckillSkuMapper.selectSkusBySpuId(spuId);
            //循环遍历,存储skulist预热数据
            List<String> skuJsons=new ArrayList<>();
            String skusKey= SeckillSkuService.SECKILL_SKUS_PREFIX+spuId;
            for (SeckillSkuVO skuVO : skus) {
                String skuJson=JSON.toJSONString(skuVO);
                //为sku的redis库存做初始化
                opsForValue.set(SeckillSkuService.SECKILL_SKU_STOCK_PREFIX+skuVO.getId(),skuVO.getStock()+"");
                skuJsons.add(skuJson);
            }
            //清除上次重启的数据,否则列表会越来越多
            stringRedisTemplate.delete(skusKey);
            opsForList.leftPushAll(skusKey,skuJsons);
            //不仅仅可以放spu列表,还可以准备spu单个对象的json
            spuVO.setUrl("/seckill/"+(new Random().nextInt(900000)+100000));
            //将对象转化成json
            String spuKey=SeckillSpuService.SPU_SECKILL_PREFIX+spuId;
            String spuJson= JSON.toJSONString(spuVO);
            opsForValue.set(spuKey,spuJson);
            spuJsons.add(spuJson);
        }
        //存储一下redis缓存list 多次重启,list列表元素会变动
        stringRedisTemplate.delete(spusKey);
        opsForList.leftPushAll(spusKey,spuJsons);

    }
    private static Boolean ENABLE_TIMER=true;
    //我们这样实现的定时任务,无法做到分布式定时
    public void stockTime() {
        ValueOperations<String, String> opsForValue = stringRedisTemplate.opsForValue();
        //每隔5秒钟执行一次
        while(ENABLE_TIMER){
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //重复循环执行,每次执行等待5秒钟
            //从数据库读取所有Sku的库存数据,并且更新到redis中
            List<SeckillSkuVO> skuVOS=seckillSkuMapper.selectAll();
            for (SeckillSkuVO skuVO : skuVOS) {
                opsForValue.set(SeckillSkuService.SECKILL_SKU_STOCK_PREFIX+skuVO.getId(),skuVO.getStock()+"");
            }
        }
    }
}
